/**
 * Created by Administrator on 2018/12/30.
 */
package com.game.fg.service;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Random;
@Component
public class FGConfig {
    private static Logger logger = LogManager.getLogger(FGConfig.class.getName());

    class Lottery {
        private int rate;//权重
        private int min;//抽奖最小值
        private int max;//抽奖最大值

        int getRate() {
            return rate;
        }

        int getMin() {
            return min;
        }

        int getMax() {
            return max;
        }

        Lottery(int rate, int min, int max) {
            this.rate = rate;
            this.min = min;
            this.max = max;
        }
    }

    class Probability {
        Probability(int winRate, int loseRate, int tieRate) {
            this.winRate = winRate;
            this.loseRate = loseRate;
            this.tieRate = tieRate;
        }

        int getWinRate() {
            return winRate;
        }

        int getTieRate() {
            return tieRate;
        }

        int getLoseRate() {
            return loseRate;
        }

        //平概率
        private int tieRate;
        //胜概率
        private int winRate;
        //输概率
        private int loseRate;
    }

    class Benefits {
        Benefits(double income, double buffer) {
            this.income = income;
            this.buffer = buffer;
        }

        double getIncome() {
            return income;
        }

        public double getBuffer() {
            return buffer;
        }

        public void setBuffer(double buffer) {
            this.buffer = buffer;
        }

        private double income;//净收入
        private double buffer;//胜率加成
    }

    class Room {
        //回合输赢概率 key:回合 value:概率
        Dictionary<Integer, Probability> probabilityDic = new Hashtable<Integer, Probability>();
        //抽奖概率
        private List<Lottery> lotteryList = new ArrayList<Lottery>();
        //该房间最高可获得的金币
        int maxMoney = 0;
        //救济金补偿相关数据（根据income升序排序）
        List<Benefits> benefitsList = new ArrayList<Benefits>();

        //获取抽奖金币
        int getLotteryMoney() {
            int totalWeight = 0;
            int curWeight = 0;
            Random rand = new Random();
            for (Lottery l : lotteryList) {
                totalWeight += l.getRate();
            }
            int randWeight = rand.nextInt(totalWeight);
            for (Lottery l : lotteryList) {
                curWeight += l.getRate();
                if (curWeight > randWeight) {
                    return rand.nextInt(l.getMax()) % (l.getMax() - l.getMin() + 1) + l.getMin();
                }
            }
            return 0;
        }

        //根据玩家净收入获取buffer
        double getBuffer(double income) {
            double buffer = 0;
            for (Benefits b : benefitsList) {
                if (income <= b.getIncome()) {
                    return b.getBuffer();
                }
            }
            return buffer;
        }

        void parseConfig(JSONObject config) {
            JSONObject p = config.getJSONObject("probability");
            String[] roundList = p.getString("round").split("\\|");
            String[] winList = p.getString("win").split("\\|");
            String[] loseList = p.getString("lose").split("\\|");
            String[] tieList = p.getString("tie").split("\\|");
            for (int i = 0; i < roundList.length; i++) {
                probabilityDic.put(Integer.parseInt(roundList[i]),
                        new Probability(Integer.parseInt(winList[i]),
                                Integer.parseInt(loseList[i]),
                                Integer.parseInt(tieList[i])));
            }
            //抽奖配置
            JSONObject l = config.getJSONObject("lottery");
            String[] rateList = l.getString("rate").split("\\|");
            String[] minList = l.getString("min").split("\\|");
            String[] maxList = l.getString("max").split("\\|");
            for (int i = 0; i < rateList.length; i++) {
                int rate = Integer.parseInt(rateList[i]);
                int min = Integer.parseInt(minList[i]);
                int max = Integer.parseInt(maxList[i]);
                lotteryList.add(new Lottery(rate, min, max));
                maxMoney = max;
            }
            //救济金配置
            JSONObject b = config.getJSONObject("benefits");
            String[] incomeList = b.getString("income").split("\\|");
            String[] bufferList = b.getString("buffer").split("\\|");
            for (int i = 0; i < incomeList.length; i++) {
                double income = Integer.parseInt(incomeList[i]);
                double buffer = Integer.parseInt(bufferList[i]);
                benefitsList.add(new Benefits(income, buffer));
            }
            Collections.sort(benefitsList, new Comparator<Benefits>() {
                public int compare(Benefits p1, Benefits p2) {
                    //按照Person的年龄进行升序排列
                    if (p1.getIncome() > p2.getIncome()) {
                        return 1;
                    }
                    if (p1.getIncome() == p2.getIncome()) {
                        return 0;
                    }
                    return -1;
                }
            });
        }
    }

    class RoomConfig {
        //回合输赢概率 key:回合 value:概率
        private Room roomOfJunior = new Room();
        private Room roomOfMiddle = new Room();
        private Room roomOfSenior = new Room();

        //根据房间类型获取房间信息
        Room getRoom(Message.EnumRoomType roomType) {
            if (roomType == Message.EnumRoomType.JUNIOR) {
                return roomOfJunior;
            } else if (roomType == Message.EnumRoomType.MIDDLE) {
                return roomOfMiddle;
            }
            return roomOfSenior;
        }

        //解析配置
        void parseConfig(JSONObject config) {
            roomOfJunior.parseConfig(config.getJSONObject("junior"));
            roomOfMiddle.parseConfig(config.getJSONObject("middle"));
            roomOfSenior.parseConfig(config.getJSONObject("senior"));
        }
    }

    class ServerConfig {
        int getWsPort() {
            return wsPort;
        }

        void setWsPort(int wsPort) {
            this.wsPort = wsPort;
        }

        String getDbUrl() {
            return dbUrl;
        }

        void setDbUrl(String dbUrl) {
            this.dbUrl = dbUrl;
        }

        String getDbUser() {
            return dbUser;
        }

        void setDbUser(String dbUser) {
            this.dbUser = dbUser;
        }

        String getDbPassword() {
            return dbPassword;
        }

        void setDbPassword(String dbPassword) {
            this.dbPassword = dbPassword;
        }

        String getManagerServerIP() {
            return managerServerIP;
        }

        void setManagerServerIP(String managerServerIP) {
            this.managerServerIP = managerServerIP;
        }

        int getManagerServerPort() {
            return managerServerPort;
        }

        void setManagerServerPort(int managerServerPort) {
            this.managerServerPort = managerServerPort;
        }

        String getWs_ip() {
            return ws_ip;
        }

        void setWs_ip(String ws_ip) {
            this.ws_ip = ws_ip;
        }

        String getGame() {
            return game;
        }

        void setGame(String game) {
            this.game = game;
        }

        String getAuthServerIP() {
            return authServerIP;
        }

        void setAuthServerIP(String authServerIP) {
            this.authServerIP = authServerIP;
        }

        int getAuthServerPort() {
            return authServerPort;
        }

        void setAuthServerPort(int authServerPort) {
            this.authServerPort = authServerPort;
        }

        String getMqServerIP() {
            return mqServerIP;
        }

        void setMqServerIP(String mqServerIP) {
            this.mqServerIP = mqServerIP;
        }

        int getMqServerPort() {
            return mqServerPort;
        }

        void setMqServerPort(int mqServerPort) {
            this.mqServerPort = mqServerPort;
        }

        String getExchangeUrl() {
            return exchangeUrl;
        }

        void setExchangeUrl(String exchangeUrl) {
            this.exchangeUrl = exchangeUrl;
        }

        String getGlobalCoinUrl() {
            return globalCoinUrl;
        }

        void setGlobalCoinUrl(String globalCoinUrl) {
            this.globalCoinUrl = globalCoinUrl;
        }

        String getRedisHost() {
            return redisHost;
        }

        void setRedisHost(String redisHost) {
            this.redisHost = redisHost;
        }

        int getRedisPort() {
            return redisPort;
        }

        void setRedisPort(int redisPort) {
            this.redisPort = redisPort;
        }

        String getRedisPassword() {
            return redisPassword;
        }

        void setRedisPassword(String redisPassword) {
            this.redisPassword = redisPassword;
        }

        private String game;//游戏名称
        private String ws_ip;//web socket 地址
        private int wsPort;//web socket 监听的端口

        private String dbUrl;//数据库链接url
        private String dbUser;//数据库用户
        private String dbPassword;//数据库用户密码


        private String redisHost;//redis ip
        private int redisPort;//redis 端口
        private String redisPassword;//redis 密码


        private String managerServerIP;//管理服务器IP
        private int managerServerPort;//管理服务器端口
        private String authServerIP;//验证服务器IP
        private int authServerPort;//验证服务器端口
        private String mqServerIP;//验证服务器IP
        private int mqServerPort;//验证服务器端口
        private String exchangeUrl;//兑换金币url
        private String globalCoinUrl;//全球救济金url


    }

    //报名费
    int entryFeeOfJunior = 0;//初级房报名费
    int entryFeeOfMiddle = 0;//中级房报名费
    int entryFeeOfSenior = 0;//高级房报名费
    //奖池安全线
    private int safeLineOfJunior = 0;//初级房安全线
    private int safeLineOfMiddle = 0;//中级房安全线
    private int safeLineOfSenior = 0;//高级房安全线
    //抽税率
    int taxRateOfNormal = 0;//正常抽税率
    int taxRateOfAbnormal = 0;//非正常抽税率


    //每次最多可领取的救济金
    private int userMaxGetBenefits = 0;
    //正常配置
    private RoomConfig normalConfig = new RoomConfig();
    //非正常配置
    private RoomConfig abnormalConfig = new RoomConfig();
    //服务器配置
    ServerConfig serverConfig = new ServerConfig();


    //获取安全、房间类型、回合获得输赢平概率
    Probability getProbabilityByRound(boolean normal, Message.EnumRoomType roomType, int round) {
        RoomConfig config = normal ? normalConfig : abnormalConfig;
        Room room = config.getRoom(roomType);
        return room.probabilityDic.get(round);
    }


    //根据房间类型获取报名费
    int getEntryFee(Message.EnumRoomType roomType) {
        if (roomType == Message.EnumRoomType.JUNIOR) {
            return entryFeeOfJunior;
        } else if (roomType == Message.EnumRoomType.MIDDLE) {
            return entryFeeOfMiddle;
        }
        return entryFeeOfSenior;
    }

    //根据房间类型获取安全线
    int getSafeLine(Message.EnumRoomType roomType) {
        if (roomType == Message.EnumRoomType.JUNIOR) {
            return safeLineOfJunior;
        } else if (roomType == Message.EnumRoomType.MIDDLE) {
            return safeLineOfMiddle;
        }
        return safeLineOfSenior;
    }

    //根据安全、房间类型获得抽奖金币
    int getLotteryMoney(boolean normal, Message.EnumRoomType roomType) {
        RoomConfig config = normal ? normalConfig : abnormalConfig;
        Room room = config.getRoom(roomType);
        return room.getLotteryMoney();
    }

    //根据房间类型、玩家净收入获得buffer
    double getBuffer(boolean normal, Message.EnumRoomType roomType, double income) {
        RoomConfig config = normal ? normalConfig : abnormalConfig;
        Room room = config.getRoom(roomType);
        return room.getBuffer(income);
    }

    //获取管理服务器url
    String getManagerServerUrl() {
        return String.format("ws://%s:%d", serverConfig.getManagerServerIP(),
                serverConfig.getManagerServerPort());
    }

    //获取认证服务器url
    String getAuthServerUrl() {
        return String.format("ws://%s:%d", serverConfig.getAuthServerIP(),
                serverConfig.getAuthServerPort());
    }

    //获取MQ服务器url
    String getMQServerUrl() {
        return String.format("ws://%s:%d", serverConfig.getMqServerIP(),
                serverConfig.getMqServerPort());
    }

    int getUserMaxGetBenefits() {
        return userMaxGetBenefits;
    }

    //加载配置文件
    void loadConfig() {
        try {

            //String filePath = System.getProperty("user.dir") + "/fingerguessing.json";
            String filePath=FGConfig.class.getClassLoader().getResource("config/fingerguessing.json").getPath();
            InputStreamReader read = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
            BufferedReader reader = new BufferedReader(read);
            JSONObject jsonConfig = new JSONObject(org.apache.commons.io.IOUtils.toString(reader));
            //报名费
            entryFeeOfJunior = ((JSONObject) jsonConfig.get("EntryFee")).getInt("junior");
            entryFeeOfMiddle = ((JSONObject) jsonConfig.get("EntryFee")).getInt("middle");
            entryFeeOfSenior = ((JSONObject) jsonConfig.get("EntryFee")).getInt("senior");
            //安全线
            safeLineOfJunior = ((JSONObject) jsonConfig.get("SafeLine")).getInt("junior");
            safeLineOfMiddle = ((JSONObject) jsonConfig.get("SafeLine")).getInt("middle");
            safeLineOfSenior = ((JSONObject) jsonConfig.get("SafeLine")).getInt("senior");
            //抽税率
            taxRateOfNormal = ((JSONObject) jsonConfig.get("TaxRate")).getInt("normal");
            taxRateOfAbnormal = ((JSONObject) jsonConfig.get("TaxRate")).getInt("abnormal");
            //每日最多可领取的救济金
            userMaxGetBenefits = jsonConfig.getInt("UserMaxGetBenefits");
            //概率
            normalConfig.parseConfig((JSONObject) jsonConfig.get("Normal"));
            abnormalConfig.parseConfig((JSONObject) jsonConfig.get("Abnormal"));
            //加载系统配置
            //filePath = System.getProperty("user.dir") + "/server.json";
            filePath= FGConfig.class.getClassLoader().getResource("config/server.json").getPath();
            read = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
            reader = new BufferedReader(read);
            jsonConfig = new JSONObject(org.apache.commons.io.IOUtils.toString(reader));
            serverConfig.setGame(jsonConfig.getString("game"));
            serverConfig.setWs_ip(jsonConfig.getString("ws_ip"));
            serverConfig.setWsPort(jsonConfig.getInt("ws_port"));
            serverConfig.setDbUrl(jsonConfig.getString("db_url"));
            serverConfig.setDbUser(jsonConfig.getString("db_user"));
            serverConfig.setDbPassword(jsonConfig.getString("db_password"));
            serverConfig.setManagerServerIP(jsonConfig.getString("manager_server_ip"));
            serverConfig.setManagerServerPort(jsonConfig.getInt("manager_server_port"));
            serverConfig.setAuthServerIP(jsonConfig.getString("auth_server_ip"));
            serverConfig.setAuthServerPort(jsonConfig.getInt("auth_server_port"));
            serverConfig.setMqServerIP(jsonConfig.getString("mq_server_ip"));
            serverConfig.setMqServerPort(jsonConfig.getInt("mq_server_port"));
            //serverConfig.setExchangeUrl(jsonConfig.getString("exchange_url"));
            //serverConfig.setGlobalCoinUrl(jsonConfig.getString("global_coin_url"));

            //serverConfig.setRedisHost(jsonConfig.getString("redis_host"));
            //serverConfig.setRedisPort(jsonConfig.getInt("redis_port"));
            //serverConfig.setRedisPassword(jsonConfig.getString("redis_password"));


        } catch (Exception e) {
            logger.error("加载游戏配置表错误", e);
            System.exit(0);
        }
    }

    private FGConfig() {
    }

    private static FGConfig fgConfig = new FGConfig();

    public static FGConfig getInstance() {
        return fgConfig;
    }
}

